//! 指标收集模块
//! 
//! 提供指标收集、存储和查询功能

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::sync::RwLock;
use anyhow::Result;
use tracing::{debug, info, warn};

/// 指标类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MetricType {
    /// 计数器（只增不减）
    Counter,
    /// 仪表盘（可增可减）
    Gauge,
    /// 直方图
    Histogram,
    /// 摘要
    Summary,
}

/// 指标值
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MetricValue {
    /// 整数值
    Integer(i64),
    /// 浮点数值
    Float(f64),
    /// 直方图数据
    Histogram {
        buckets: Vec<(f64, u64)>, // (上界, 计数)
        sum: f64,
        count: u64,
    },
    /// 摘要数据
    Summary {
        quantiles: Vec<(f64, f64)>, // (分位数, 值)
        sum: f64,
        count: u64,
    },
}

impl MetricValue {
    /// 转换为浮点数（用于简单计算）
    pub fn as_float(&self) -> f64 {
        match self {
            MetricValue::Integer(i) => *i as f64,
            MetricValue::Float(f) => *f,
            MetricValue::Histogram { sum, .. } => *sum,
            MetricValue::Summary { sum, .. } => *sum,
        }
    }

    /// 获取计数（如果适用）
    pub fn count(&self) -> Option<u64> {
        match self {
            MetricValue::Histogram { count, .. } => Some(*count),
            MetricValue::Summary { count, .. } => Some(*count),
            _ => None,
        }
    }
}

/// 指标数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricData {
    /// 指标名称
    pub name: String,
    /// 指标类型
    pub metric_type: MetricType,
    /// 指标值
    pub value: MetricValue,
    /// 标签
    pub labels: HashMap<String, String>,
    /// 时间戳
    pub timestamp: u64,
    /// 帮助信息
    pub help: Option<String>,
}

impl MetricData {
    /// 创建新的指标数据
    pub fn new(
        name: String,
        metric_type: MetricType,
        value: MetricValue,
        labels: HashMap<String, String>,
    ) -> Self {
        Self {
            name,
            metric_type,
            value,
            labels,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
            help: None,
        }
    }

    /// 设置帮助信息
    pub fn with_help(mut self, help: String) -> Self {
        self.help = Some(help);
        self
    }

    /// 获取标签字符串（用于唯一标识）
    pub fn label_string(&self) -> String {
        let mut labels: Vec<_> = self.labels.iter().collect();
        labels.sort_by_key(|(k, _)| *k);
        labels
            .iter()
            .map(|(k, v)| format!("{}=\"{}\"", k, v))
            .collect::<Vec<_>>()
            .join(",")
    }

    /// 获取完整的指标标识符
    pub fn metric_id(&self) -> String {
        if self.labels.is_empty() {
            self.name.clone()
        } else {
            format!("{}[{}]", self.name, self.label_string())
        }
    }
}

/// 指标收集器
pub struct MetricsCollector {
    /// 存储的指标数据
    metrics: Arc<RwLock<HashMap<String, MetricData>>>,
    /// 指标定义
    metric_definitions: Arc<RwLock<HashMap<String, MetricDefinition>>>,
}

/// 指标定义
#[derive(Debug, Clone)]
pub struct MetricDefinition {
    /// 指标名称
    pub name: String,
    /// 指标类型
    pub metric_type: MetricType,
    /// 帮助信息
    pub help: String,
    /// 标签名称列表
    pub label_names: Vec<String>,
}

impl MetricsCollector {
    /// 创建新的指标收集器
    pub fn new() -> Self {
        Self {
            metrics: Arc::new(RwLock::new(HashMap::new())),
            metric_definitions: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// 注册指标定义
    pub async fn register_metric(&self, definition: MetricDefinition) -> Result<()> {
        let mut definitions = self.metric_definitions.write().await;
        definitions.insert(definition.name.clone(), definition);
        info!("注册指标定义: {}", definitions.len());
        Ok(())
    }

    /// 记录指标
    pub async fn record_metric(
        &self,
        name: &str,
        value: MetricValue,
        labels: HashMap<String, String>,
    ) -> Result<()> {
        // 验证指标定义
        let definitions = self.metric_definitions.read().await;
        let definition = definitions.get(name);
        
        let metric_type = if let Some(def) = definition {
            // 验证标签
            for label_name in &def.label_names {
                if !labels.contains_key(label_name) {
                    warn!("指标 {} 缺少必需的标签: {}", name, label_name);
                }
            }
            def.metric_type.clone()
        } else {
            // 如果没有定义，默认为Gauge类型
            warn!("指标 {} 未注册，使用默认类型 Gauge", name);
            MetricType::Gauge
        };

        let metric_data = MetricData::new(name.to_string(), metric_type, value, labels);
        let metric_id = metric_data.metric_id();

        let mut metrics = self.metrics.write().await;
        
        // 对于Counter类型，需要累加值
        if metric_data.metric_type == MetricType::Counter {
            if let Some(existing) = metrics.get(&metric_id) {
                let new_value = match (&existing.value, &metric_data.value) {
                    (MetricValue::Integer(old), MetricValue::Integer(new)) => {
                        MetricValue::Integer(old + new)
                    }
                    (MetricValue::Float(old), MetricValue::Float(new)) => {
                        MetricValue::Float(old + new)
                    }
                    (MetricValue::Integer(old), MetricValue::Float(new)) => {
                        MetricValue::Float(*old as f64 + new)
                    }
                    (MetricValue::Float(old), MetricValue::Integer(new)) => {
                        MetricValue::Float(old + *new as f64)
                    }
                    _ => metric_data.value.clone(),
                };
                
                let mut updated_metric = metric_data.clone();
                updated_metric.value = new_value;
                metrics.insert(metric_id, updated_metric);
            } else {
                metrics.insert(metric_id, metric_data);
            }
        } else {
            // 对于其他类型，直接替换
            metrics.insert(metric_id, metric_data);
        }

        debug!("记录指标: {} = {:?}", name, value);
        Ok(())
    }

    /// 获取所有指标
    pub async fn get_metrics(&self) -> Result<Vec<MetricData>> {
        let metrics = self.metrics.read().await;
        Ok(metrics.values().cloned().collect())
    }

    /// 获取指定名称的指标
    pub async fn get_metric(&self, name: &str) -> Result<Vec<MetricData>> {
        let metrics = self.metrics.read().await;
        Ok(metrics
            .values()
            .filter(|m| m.name == name)
            .cloned()
            .collect())
    }

    /// 获取指标数量
    pub async fn metric_count(&self) -> usize {
        let metrics = self.metrics.read().await;
        metrics.len()
    }

    /// 清空所有指标
    pub async fn clear_metrics(&self) -> Result<()> {
        let mut metrics = self.metrics.write().await;
        metrics.clear();
        info!("清空所有指标");
        Ok(())
    }

    /// 收集系统指标
    pub async fn collect_metrics(&self) -> Result<()> {
        // 收集基本的运行时指标
        self.collect_runtime_metrics().await?;
        
        // 收集内存使用指标
        self.collect_memory_metrics().await?;
        
        debug!("指标收集完成");
        Ok(())
    }

    /// 收集运行时指标
    async fn collect_runtime_metrics(&self) -> Result<()> {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs();

        // 记录当前时间戳
        self.record_metric(
            "runtime_timestamp",
            MetricValue::Integer(now as i64),
            HashMap::new(),
        ).await?;

        // 记录活跃任务数（模拟）
        self.record_metric(
            "runtime_active_tasks",
            MetricValue::Integer(tokio::runtime::Handle::current().metrics().active_tasks_count() as i64),
            HashMap::new(),
        ).await?;

        Ok(())
    }

    /// 收集内存使用指标
    async fn collect_memory_metrics(&self) -> Result<()> {
        // 这里可以集成更详细的内存监控
        // 目前使用简单的模拟数据
        
        let mut labels = HashMap::new();
        labels.insert("type".to_string(), "heap".to_string());
        
        // 模拟内存使用情况
        self.record_metric(
            "memory_usage_bytes",
            MetricValue::Integer(1024 * 1024 * 100), // 100MB
            labels,
        ).await?;

        Ok(())
    }
}

impl Default for MetricsCollector {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_metrics_collector_creation() {
        let collector = MetricsCollector::new();
        assert_eq!(collector.metric_count().await, 0);
    }

    #[tokio::test]
    async fn test_metric_registration() {
        let collector = MetricsCollector::new();
        
        let definition = MetricDefinition {
            name: "test_counter".to_string(),
            metric_type: MetricType::Counter,
            help: "Test counter metric".to_string(),
            label_names: vec!["service".to_string()],
        };
        
        collector.register_metric(definition).await.unwrap();
        
        let mut labels = HashMap::new();
        labels.insert("service".to_string(), "test".to_string());
        
        collector.record_metric("test_counter", MetricValue::Integer(1), labels).await.unwrap();
        
        let metrics = collector.get_metrics().await.unwrap();
        assert_eq!(metrics.len(), 1);
        assert_eq!(metrics[0].name, "test_counter");
    }

    #[tokio::test]
    async fn test_counter_accumulation() {
        let collector = MetricsCollector::new();
        
        let definition = MetricDefinition {
            name: "requests_total".to_string(),
            metric_type: MetricType::Counter,
            help: "Total requests".to_string(),
            label_names: vec![],
        };
        
        collector.register_metric(definition).await.unwrap();
        
        // 记录多次计数
        collector.record_metric("requests_total", MetricValue::Integer(5), HashMap::new()).await.unwrap();
        collector.record_metric("requests_total", MetricValue::Integer(3), HashMap::new()).await.unwrap();
        collector.record_metric("requests_total", MetricValue::Integer(2), HashMap::new()).await.unwrap();
        
        let metrics = collector.get_metric("requests_total").await.unwrap();
        assert_eq!(metrics.len(), 1);
        
        if let MetricValue::Integer(value) = &metrics[0].value {
            assert_eq!(*value, 10); // 5 + 3 + 2
        } else {
            panic!("Expected integer value");
        }
    }

    #[tokio::test]
    async fn test_gauge_replacement() {
        let collector = MetricsCollector::new();
        
        let definition = MetricDefinition {
            name: "temperature".to_string(),
            metric_type: MetricType::Gauge,
            help: "Current temperature".to_string(),
            label_names: vec![],
        };
        
        collector.register_metric(definition).await.unwrap();
        
        // 记录多次测量值
        collector.record_metric("temperature", MetricValue::Float(25.5), HashMap::new()).await.unwrap();
        collector.record_metric("temperature", MetricValue::Float(26.0), HashMap::new()).await.unwrap();
        
        let metrics = collector.get_metric("temperature").await.unwrap();
        assert_eq!(metrics.len(), 1);
        
        if let MetricValue::Float(value) = &metrics[0].value {
            assert_eq!(*value, 26.0); // 最后一个值
        } else {
            panic!("Expected float value");
        }
    }

    #[tokio::test]
    async fn test_metric_with_labels() {
        let collector = MetricsCollector::new();
        
        let mut labels1 = HashMap::new();
        labels1.insert("method".to_string(), "GET".to_string());
        labels1.insert("status".to_string(), "200".to_string());
        
        let mut labels2 = HashMap::new();
        labels2.insert("method".to_string(), "POST".to_string());
        labels2.insert("status".to_string(), "404".to_string());
        
        collector.record_metric("http_requests", MetricValue::Integer(10), labels1).await.unwrap();
        collector.record_metric("http_requests", MetricValue::Integer(5), labels2).await.unwrap();
        
        let metrics = collector.get_metric("http_requests").await.unwrap();
        assert_eq!(metrics.len(), 2);
    }

    #[test]
    fn test_metric_value_conversion() {
        let int_value = MetricValue::Integer(42);
        assert_eq!(int_value.as_float(), 42.0);
        
        let float_value = MetricValue::Float(3.14);
        assert_eq!(float_value.as_float(), 3.14);
        
        let histogram_value = MetricValue::Histogram {
            buckets: vec![(1.0, 10), (5.0, 20)],
            sum: 100.0,
            count: 30,
        };
        assert_eq!(histogram_value.as_float(), 100.0);
        assert_eq!(histogram_value.count(), Some(30));
    }

    #[test]
    fn test_metric_data_id() {
        let mut labels = HashMap::new();
        labels.insert("service".to_string(), "api".to_string());
        labels.insert("method".to_string(), "GET".to_string());
        
        let metric = MetricData::new(
            "requests_total".to_string(),
            MetricType::Counter,
            MetricValue::Integer(1),
            labels,
        );
        
        let id = metric.metric_id();
        assert!(id.contains("requests_total"));
        assert!(id.contains("method=\"GET\""));
        assert!(id.contains("service=\"api\""));
    }
}
